const nbObjects = 800;
var conf, scene, camera, cameraCtrl, light, renderer;
var whw, whh;

var objects;
var spriteMap, spriteMaterial;

var mouse = new THREE.Vector2();
var mouseOver = false;
var mousePlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
var mousePosition = new THREE.Vector3();
var raycaster = new THREE.Raycaster();

function init() {
	conf = {
		opacity: 0.8
	};

	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 0.1, 1000);
	cameraCtrl = new THREE.OrbitControls(camera);
	cameraCtrl.autoRotate = true;
	cameraCtrl.autoRotateSpeed = 5;

	renderer = new THREE.WebGLRenderer();
	renderer.setSize(window.innerWidth, window.innerHeight);
	document.body.appendChild(renderer.domElement);

	initScene();

	onWindowResize();
	window.addEventListener('resize', onWindowResize, false);

	animate();
};

function initScene() {
	scene = new THREE.Scene();
	scene.background = new THREE.Color(0x000000);

	camera.position.z = 30;
	camera.position.y = 20;
	camera.lookAt(0, 0, 0);

	spriteMap = new THREE.Texture();
	var bubble = new Image();
	bubble.src =
		"";
	bubble.onload = function() {
		spriteMap.image = bubble;
		spriteMap.needsUpdate = true;
	};

	objects = [];
	for (var i = 0; i < nbObjects; i++) {
		var object = new Truc();
		objects.push(object);
		scene.add(object.sprite);
	}
}

function animate() {
	requestAnimationFrame(animate);

	cameraCtrl.update();

	renderer.render(scene, camera);
};

function Truc() {
	this.init();
	this.shuffle();
}

Truc.prototype.init = function() {
	this.material = new THREE.SpriteMaterial({
		color: randomColor({
			luminosity: 'light'
		}),
		map: spriteMap,
		transparent: true,
		opacity: 1,
		depthTest: false,
		depthWrite: false,
		blending: THREE.AdditiveBlending
	});
	this.sprite = new THREE.Sprite(this.material);
};

Truc.prototype.shuffle = function() {
	this.scale1 = 0.1;
	this.scale2 = 2 + rnd(3);
	this.sprite.scale.set(this.scale1, this.scale1, 1);

	var rndv = getRandomVec3();
	this.sprite.position.set(rndv.x, rndv.y, rndv.z).multiplyScalar(50);
	this.sprite.position.y -= 25;

	this.material.opacity = conf.opacity;

	this.tt = this.scale2;
	TweenMax.to(this.sprite.scale, 1, {
		x: this.scale2,
		y: this.scale2,
		ease: Power2.easeIn
	});
	TweenMax.to(this.sprite.position, this.scale2, {
		y: this.sprite.position.y + 100,
		ease: Power2.easeIn
	});

	this.t1 = 1;
	TweenMax.to(this.sprite.position, this.t1, {
		x: this.sprite.position.x + rnd(10, true),
		z: this.sprite.position.z + rnd(10, true),
		ease: Linear.ease,
		repeat: Math.floor((this.tt / this.t1) / 2),
		yoyo: true
	});

	TweenMax.to(this.material, 1, {
		opacity: 0,
		delay: this.tt - 1,
		ease: Power2.easeIn,
		onCompleteParams: [this],
		onComplete: function(o) {
			o.shuffle();
		}
	});
};

function getRandomVec3() {
	const u = Math.random();
	const v = Math.random();
	const theta = u * 2.0 * Math.PI;
	const phi = Math.acos(2.0 * v - 1.0);
	const r = Math.cbrt(Math.random());
	const sinTheta = Math.sin(theta);
	const cosTheta = Math.cos(theta);
	const sinPhi = Math.sin(phi);
	const cosPhi = Math.cos(phi);
	const x = r * sinPhi * cosTheta;
	const y = r * sinPhi * sinTheta;
	const z = r * cosPhi;
	return {
		x: x,
		y: y,
		z: z
	};
}

function rnd(max, negative) {
	return negative ? Math.random() * 2 * max - max : Math.random() * max;
}

function onWindowResize() {
	whw = window.innerWidth / 2;
	whh = window.innerHeight / 2;
	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	renderer.setSize(window.innerWidth, window.innerHeight);
}

init();
